{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 介绍\n",
    "\n",
    "千帆大模型平台现已支持用户使用 ERNIE-Bot 模型与 ERNIE-Bot-4 模型的 Function Call 功能。Function Call 功能允许用户向大模型传递其可以使用的工具集合，并且通过使用该集合中的工具来解决问题。\n",
    "\n",
    "千帆 Python SDK 在 Function Call 的基础上，与 Langchain 的 Agent 理念进行结合，推出了以 Function Call 功能实现的千帆 Agent 模块。下面将通过一个简单的搜索任务 Demo，来演示该模块的使用效果。\n",
    "\n",
    "# 准备工作\n",
    "\n",
    "若需要执行该 Demo，用户首先需要保证目前使用的 Python 版本高于 **3.8**，且安装最新版本的千帆 Python SDK 、 Wikipedia 与 arxiv 包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install qianfan # >= 0.1.3\n",
    "!pip install wikipedia==1.4.0\n",
    "!pip install arxiv==2.0.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然后根据[文档](https://cloud.baidu.com/doc/WENXINWORKSHOP/s/3lmokh7n6)指引申请API Key（即AK）和 Secret Key（即SK），这些都会在后续的流程中使用到。\n",
    "\n",
    "# 设置\n",
    "\n",
    "首先设置好你所申请到的千帆 AK 与 SK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ['QIANFAN_AK'] = \"your_ak\"\n",
    "os.environ['QIANFAN_SK'] = \"your_sk\""
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其次创建对应 ERNIE-Bot 或者 ERNIE-Bot-4 模型的 Langchain Chat Model。model 字段支持使用`ERNIE-Bot`。 `ERNIE-Bot-4` 也会在将来支持function_call功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import QianfanChatEndpoint\n",
    "\n",
    "qianfan_chat_model = QianfanChatEndpoint(model=\"ERNIE-Bot\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在这之后，我们还需要创建传递给大模型的工具集。这里我们使用 Langchain 内自带的 Wikipedia 搜索 和 Arxiv 搜索工具。为了能够保证搜索结果在中文方面的相关性，此处我们设置了一些参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.tools import WikipediaQueryRun, ArxivQueryRun\n",
    "from langchain.utilities import ArxivAPIWrapper, WikipediaAPIWrapper\n",
    "\n",
    "tools = [\n",
    "    ArxivQueryRun(\n",
    "        description=\"这是一个论文搜索的工具\"\n",
    "        \"当你需要查询论文的时候，请使用这个工具\"\n",
    "        \"输入应该是一条你所需要查询的论文的信息\"\n",
    "        ,\n",
    "        api_wrapper=ArxivAPIWrapper(top_k_results=1)\n",
    "    ),\n",
    "    WikipediaQueryRun(\n",
    "        description=\"这是一个维基百科的调用工具.\"\n",
    "        \"当你需要查询有关论文作者、历史的百科信息时，请使用这个工具\"\n",
    "        \"输入应该是一条你所需要查询的内容\",\n",
    "        api_wrapper=WikipediaAPIWrapper(load_all_available_meta=True)\n",
    "    )\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果你想编写属于自己的工具，可以参考这篇 [Langchain 的官方文档](https://python.langchain.com/docs/modules/agents/tools/custom_tools#using-the-tool-decorator)\n",
    "\n",
    "在准备好上述组件后，我们就需要引入 Function Call 相关的千帆 Agent 组件了。\n",
    "\n",
    "# 千帆 Agent\n",
    "\n",
    "千帆 Agent 共分为两种：`QianfanSingleActionAgent` 和 `QianfanMultiActionAgent` ，两者的区别在于并行度的不同，前者为串行执行，一次规划只能使用一个工具；后者为并行执行，一次规划可以同时使用多个工具，但是规划的结果更加不稳定。在实际使用时，我们推荐使用 `QianfanSingleActionAgent` ，其能够在绝大多数场合下契合你的需求。本 Demo 使用 `QianfanSingleActionAgent` 进行演示。\n",
    "\n",
    "用户只需要如下图所示，调用工厂方法 `from_system_prompt` 即可创建一个千帆 Agent，并且作为 Langchain AgentExcutor 的参数传入。`from_system_prompt` 除了接受 `tools` 工具列表和 `llm` 以外，还支持用户传入名为 `system_prompt` 的可选 prompt，作为最终上报的 system 字段内容。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import AgentExecutor\n",
    "\n",
    "from qianfan.extensions.langchain.agents import QianfanSingleActionAgent\n",
    "\n",
    "qianfan_agent = QianfanSingleActionAgent.from_system_prompt(tools, qianfan_chat_model)\n",
    "excutor = AgentExecutor(agent=qianfan_agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然后我们就可以尝试去提问了。比如说，让 Agent 来帮我随便查询一篇有关 physics 的论文，并且返回作者的百科信息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "excutor.run(\"帮我查询physics领域论文，以及作者的百科信息\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 结语\n",
    "\n",
    "受限于可以免费使用的工具数量少，质量参差不齐；以及现有的大模型能力限制，目前 Agent 的体验还远远算不上优秀。\n",
    "\n",
    "如果读者在阅读该 demo 时遇到了什么问题或想提出意见，欢迎在项目中留下你的 issue。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "vscode": {
   "interpreter": {
    "hash": "58f7cb64c3a06383b7f18d2a11305edccbad427293a2b4afa7abe8bfc810d4bb"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
